package com.changpei.search.utils;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 *
 *
 * @author Way on 2021/8/9
 */
@Slf4j
public class SearchUtil {

    /**
     * 构建基本查询
     *
     * @param pageNum
     * @param pageSize
     * @param object
     * @return
     */
    public static NativeSearchQueryBuilder buildBasicQuery(Object object, int pageNum, int pageSize) {
        // 查询构建器
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        // 构建布尔查询
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

        // 添加参数
        Map<String, Object> param = objectToMap(object);
        if (!param.isEmpty()) {
            Set<Map.Entry<String, Object>> entries = param.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                String key = entry.getKey();
                Object value = entry.getValue();
                if (key.startsWith("ID_")) {
                    // 添加默认排序
                    nativeSearchQueryBuilder
                            .withSort(SortBuilders
                                    // 默认排序字段 -> 主键
                                    .fieldSort(key.replace("ID_", ""))
                                    .order(SortOrder.fromString(value.toString())));
                } else {
                    // 添加查询参数
                    queryBuilder.must(QueryBuilders.matchQuery(key, value));
                }
            }

            // 添加过滤
            nativeSearchQueryBuilder.withQuery(queryBuilder);
        }

        // 添加分页
        nativeSearchQueryBuilder.withPageable(PageRequest.of(pageNum - 1, pageSize));

        return nativeSearchQueryBuilder;
    }

    /**
     * 只添加有值的数据
     *
     * @param obj
     * @return
     */
    private static Map<String, Object> objectToMap(Object obj) {
        Map<String, Object> map = new LinkedHashMap<>();
        if (ObjectUtils.isEmpty(obj)) {
            return new LinkedHashMap<>();
        }
        Class<?> clazz = obj.getClass();
        try {
            for (Field field : clazz.getDeclaredFields()) {
                // 开启私有属性访问权限
                field.setAccessible(true);
                String fieldName = field.getName();

                // 是否拥有指定注解类 -> 判断主键 -> 主要用于默认升序排序
                if (!ObjectUtils.isEmpty(field.getAnnotation(Id.class))) {
                    map.put("ID_" + fieldName, "ASC");
                }
                // 过滤序列化属性
                if (!fieldName.startsWith("serial")) {
                    Object value = field.get(obj);
                    // 过滤空属性
                    if (!ObjectUtils.isEmpty(value)) {
                        map.put(fieldName, value);
                    }
                }
            }
        } catch (Exception e) {
            log.info("对象转为Map失败：{}", e.getMessage());
            e.printStackTrace();
        }
        return map;
    }
}
